using System.Collections.Generic;
using Gameplay.PVE.Config;
using Gameplay.PVE.Utils;
using UnityEditor;
using UnityEngine;

namespace Gameplay.PVE.Editor
{
    public class RpgEditorUnit
    {
        private GameObject gameObject;
        private Animator animator;
        private PveSkillConfig config;
        private int state = 0;
        private List<bool> bulletStateList = new List<bool>();
        private float skillStartTime;
        private List<Transform> gunPoints;
        private List<Transform> hitPoints;
        private List<Bullet> bulletList = new List<Bullet>();
        private List<Muzzle> muzzleList = new List<Muzzle>();
        private int muzzleId;
        private int bulletId;
        private int trailId;
        private float bulletSpeed;
        private float duration;
        private float interval;
        private int count;
        private int hitId;
        private int type;
        private int bulletCount = 0;

        public void Dispose()
        {
            for (int i = 0; i < muzzleList.Count; i++)
            {
                GameObject.DestroyImmediate(muzzleList[i].obj);
            }
            muzzleList.Clear();

            for (int i = 0; i < bulletList.Count; i++)
            {
                GameObject.DestroyImmediate(bulletList[i].obj);
            }
            bulletList.Clear();
            GameObject.DestroyImmediate(gameObject);
        }
        
        public Vector3 GetHitPoint()
        {
            if (hitPoints != null && hitPoints.Count > 0)
            {
                return hitPoints[Random.Range(0, hitPoints.Count)].position;
            }

            return new Vector3(0,1,0) + gameObject.transform.position;
        }

        private Vector3 GetGunPoint()
        {
            if (gunPoints != null && gunPoints.Count > 0)
            {
                return gunPoints[0].position + Vector3.right * 0.3f;
            }
            return new Vector3(0,1,0) + gameObject.transform.position;
        }

        private class Bullet
        {
            public GameObject obj;
            public GameObject trail;
            public Vector3 targetPosition;
            public float endTime;
        }

        private class Muzzle
        {
            public GameObject obj;
            public float endTime;
        }

        public void SetPosition(Vector3 position)
        {
            gameObject.transform.position = position;
        }

        public void SetForward(Vector3 forward)
        {
            gameObject.transform.forward = forward;
        }
        
        public void Init(int id)
        {
            var heroConfig = PveUtils.GetHeroConfig(id);
            config = PveUtils.GetSkillConfig(heroConfig.rpgNormalAttackId);
            gameObject = Object.Instantiate(AssetDatabase.LoadAssetAtPath<GameObject>(PveResourceManager.GetHeroPath(heroConfig.modelId)+".prefab"));
            animator = gameObject.GetComponentInChildren<Animator>();
            
            var modelHitPoint = gameObject.GetComponent<ModelHitPoint>();
            if (modelHitPoint != null)
            {
                gunPoints = new List<Transform>();
                for (int i = 0; i < modelHitPoint.gunPoints.Count; i++)
                {
                    gunPoints.Add(modelHitPoint.gunPoints[i]);
                }
                hitPoints = new List<Transform>();
                for (int i = 0; i < modelHitPoint.hitPoints.Count; i++)
                {
                    hitPoints.Add(modelHitPoint.hitPoints[i]);
                }
            }

            if (id == 0)
            {
                muzzleId = (int) ESkillEffect.muzzleHG;
            }
        }
        
        public void Update()
        {
            if (state == 1)
            {
                for (int i = 0; i < config.bullets.Count; i++)
                {
                    if (TimeManager.logicTime - skillStartTime >= 35/30f)
                    {
                        state = 2;
                    }
                }
            }
            else if (state == 2)
            {
                if (type == 0)
                {
                    var targetPosition = RpgShootEditorManager.Instance.GetEnemyHitPoint(IsShootGround);
                    var startPosition = GetGunPoint();
                    CreateBullet(startPosition,targetPosition);
                    state = 0;
                    /*GameObject.DestroyImmediate(muzzleEffect);
                    muzzleEffect = null;*/
                }
                else if (type == 1)
                {
                    animator.speed = 0;
                    animator.SetFloat("Speed",0);
                    if (TimeManager.logicTime - skillStartTime >= interval)
                    {
                        skillStartTime = TimeManager.logicTime;
                        var targetPosition = RpgShootEditorManager.Instance.GetEnemyHitPoint(IsShootGround);
                        var startPosition = GetGunPoint();
                        CreateBullet(startPosition,targetPosition);
                        bulletCount++;
                        if (bulletCount > count)
                        {
                            //GameObject.DestroyImmediate(muzzleEffect);
                            //muzzleEffect = null;
                            animator.speed = 1;
                            animator.SetFloat("Speed",1);
                            state = 0;
                        }
                    }
                }
                else if (type == 2)
                {
                    for (float i = -30; i <= 30f; i += 10)
                    {
                        var startPosition = GetGunPoint();
                        var targetPosition = RpgShootEditorManager.Instance.GetEnemyHitPoint(IsShootGround);
                        
                        CreateBullet(startPosition,targetPosition);
                    }
                    state = 0;
                }
            }

            for (int i = 0; i < muzzleList.Count; i++)
            {
                if (TimeManager.logicTime > muzzleList[i].endTime)
                {
                    GameObject.DestroyImmediate(muzzleList[i].obj);
                    muzzleList.RemoveAt(i);
                    i--;
                }
            }

            for (int i = 0; i < bulletList.Count; i++)
            {
                if (bulletList[i].endTime != 0)
                {
                    if (TimeManager.logicTime - bulletList[i].endTime > 5)
                    {
                        GameObject.DestroyImmediate(bulletList[i].trail);
                        bulletList.RemoveAt(i);
                        i--;
                    }
                    continue;
                }
                var speedValue = bulletSpeed * Time.deltaTime;
                if (Vector3.Distance(bulletList[i].targetPosition, bulletList[i].obj.transform.position) >= speedValue)
                {
                    var speed = speedValue * (bulletList[i].targetPosition - bulletList[i].obj.transform.position).normalized;
                    bulletList[i].obj.transform.position += speed;
                    if (bulletList[i].trail != null)
                    {
                        bulletList[i].trail.transform.position += speed;
                    }
                }
                else
                {
                    if (IsShootGround)
                    {
                        var effect = Object.Instantiate(AssetDatabase.LoadAssetAtPath<GameObject>(PveResourceManager.GetEffectPath(
                                                                                                      (int)ESkillEffect.hitObstacleGround)+".prefab"));
                        effect.transform.position = bulletList[i].targetPosition;
                    }
                    else if (type != 2)
                    {
                         var effect = Object.Instantiate(AssetDatabase.LoadAssetAtPath<GameObject>(PveResourceManager.GetEffectPath(hitId)+".prefab"));
                         effect.transform.position = bulletList[i].targetPosition;
                    }

                    bulletList[i].endTime = TimeManager.logicTime;
                    GameObject.DestroyImmediate(bulletList[i].obj);
                    /*GameObject.DestroyImmediate(bulletList[i].obj);
                    bulletList.RemoveAt(i);
                    i--;*/
                }
            }
        }

        private void CreateBullet(Vector3 startPosition,Vector3 targetPosition)
        {
            var obj = Object.Instantiate(
                AssetDatabase.LoadAssetAtPath<GameObject>(PveResourceManager.GetBulletPath(bulletId)+".prefab"));
            obj.transform.position = startPosition;
            obj.transform.forward = targetPosition - startPosition;
            GameObject trail = null;
            if (trailId != 0)
            {
                trail = Object.Instantiate(
                    AssetDatabase.LoadAssetAtPath<GameObject>(PveResourceManager.GetBulletPath(trailId)+".prefab"));
                trail.transform.position = startPosition;
                trail.transform.forward = targetPosition - startPosition;
            }
            var bullet = new Bullet
            {
                obj = obj,
                targetPosition = targetPosition,
                trail = trail,
            };
            bulletList.Add(bullet);
            
            var muzzleEffect = Object.Instantiate(AssetDatabase.LoadAssetAtPath<GameObject>(PveResourceManager.GetEffectPath(muzzleId)+".prefab"));
            var muzzle = new Muzzle
            {
                endTime = TimeManager.logicTime + 0.2f,
                obj = muzzleEffect,
            };
            muzzleEffect.transform.position = GetGunPoint();
            muzzleEffect.transform.forward = gameObject.transform.forward;
            muzzleList.Add(muzzle);
        }

        private void Start()
        {
            skillStartTime = TimeManager.logicTime;
            bulletStateList.Clear();
            for (int i = 0; i < config.bullets.Count; i++)
            {
                bulletStateList.Add(false);
            }
            if (config.action_name == null)
            {
                animator.ResetTrigger("Attack");
                animator.SetTrigger("Attack");
            }
            else
            {
                animator.ResetTrigger(config.action_name);
                animator.SetTrigger(config.action_name);
            }

            bulletCount = 0;
        }

        public void SetBulletParam(float speed, float duraton, int count,int targetType = 0)
        {
            bulletSpeed = speed;
            hitId = RpgShootEditorManager.Instance.GetHitId();
            interval = duraton / count;
            this.count = count;
            this.duration = duraton;
        }

        public bool IsShootGround = false;
        
        public void StartHG()
        {
            state = 1;
            type = 0;
            bulletId = (int) EBulletEffect.bulletHG;
            muzzleId = (int) ESkillEffect.muzzleHG;
            trailId = 0;
            Start();
        }

        public void StartSMG()
        {
            state = 1;
            type = 1;
            bulletId = (int) EBulletEffect.bulletSMG;
            muzzleId = (int) ESkillEffect.muzzleSMG;
            trailId = 0;
            Start();
        }
        
        public void StartMG()
        {
            state = 1;
            type = 1;
            bulletId = (int) EBulletEffect.bulletMG;
            muzzleId = (int) ESkillEffect.muzzleMG;
            trailId = 0;
            Start();
        }
        
        public void StartAR()
        {
            state = 1;
            type = 1;
            bulletId = (int) EBulletEffect.bulletAR;
            muzzleId = (int) ESkillEffect.muzzleAR;
            trailId = 0;
            Start();
        }
        
        public void StartSG()
        {
            state = 1;
            type = 2;
            bulletId = (int) EBulletEffect.bulletSG;
            muzzleId = (int) ESkillEffect.muzzleSG;
            trailId = (int) EBulletEffect.trailSG;
            Start();
        }
        
        public void StartSR()
        {
            state = 1;
            type = 0;
            bulletId = (int) EBulletEffect.bulletSR;
            muzzleId = (int) ESkillEffect.muzzleSR;
            trailId = (int) EBulletEffect.trailSR;
            Start();
        }
    }
}